package server

import (
	"errors"
	"fmt"
	"log"
	"net/http"
	"sync"
)

// TokenValidator 定义了一个验证token的接口
type TokenValidator interface {
	// ValidateToken 验证token是否有效
	// appID: 应用ID
	// uid: 用户ID
	// token: 用户提供的token
	// 返回值: 如果验证成功返回nil，否则返回错误
	ValidateToken(appID, uid, token string) error
}

// AppTokenValidator 应用token验证器
type AppTokenValidator struct {
	// 验证函数映射表，key是appID
	validators     map[string]func(uid, token string) error
	validatorsLock sync.RWMutex
}

// NewAppTokenValidator 创建一个新的应用token验证器
func NewAppTokenValidator() *AppTokenValidator {
	return &AppTokenValidator{
		validators: make(map[string]func(uid, token string) error),
	}
}

// RegisterValidator 注册一个应用的验证函数
func (v *AppTokenValidator) RegisterValidator(appID string, validator func(uid, token string) error) {
	v.validatorsLock.Lock()
	defer v.validatorsLock.Unlock()
	v.validators[appID] = validator
	log.Printf("Registered token validator for appID: %s", appID)
}

// ValidateToken 验证token是否有效
func (v *AppTokenValidator) ValidateToken(appID, uid, token string) error {
	v.validatorsLock.RLock()
	validator, exists := v.validators[appID]
	v.validatorsLock.RUnlock()

	if !exists {
		return fmt.Errorf("no validator registered for appID: %s", appID)
	}

	return validator(uid, token)
}

// NoopTokenValidator 一个不执行任何验证的验证器，始终返回成功
type NoopTokenValidator struct{}

// ValidateToken 不执行任何验证，始终返回成功
func (v *NoopTokenValidator) ValidateToken(appID, uid, token string) error {
	log.Printf("NoopTokenValidator: appID=%s, uid=%s, token=%s", appID, uid, token)
	return nil
}

// HTTPTokenValidator 通过HTTP请求验证token
type HTTPTokenValidator struct {
	// 验证URL映射表，key是appID
	urls     map[string]string
	urlsLock sync.RWMutex
	// HTTP客户端
	client *http.Client
}

// NewHTTPTokenValidator 创建一个新的HTTP token验证器
func NewHTTPTokenValidator() *HTTPTokenValidator {
	return &HTTPTokenValidator{
		urls:   make(map[string]string),
		client: &http.Client{Timeout: defaultHTTPTimeout},
	}
}

// RegisterURL 注册一个应用的验证URL
func (v *HTTPTokenValidator) RegisterURL(appID, url string) {
	v.urlsLock.Lock()
	defer v.urlsLock.Unlock()
	v.urls[appID] = url
	log.Printf("Registered token validation URL for appID: %s, URL: %s", appID, url)
}

// ValidateToken 通过HTTP请求验证token
func (v *HTTPTokenValidator) ValidateToken(appID, uid, token string) error {
	v.urlsLock.RLock()
	url, exists := v.urls[appID]
	v.urlsLock.RUnlock()

	if !exists {
		return fmt.Errorf("no validation URL registered for appID: %s", appID)
	}

	// 创建请求
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return fmt.Errorf("failed to create HTTP request: %v", err)
	}

	// 添加查询参数
	q := req.URL.Query()
	q.Add("appid", appID)
	q.Add("uid", uid)
	q.Add("token", token)
	req.URL.RawQuery = q.Encode()

	// 发送请求
	resp, err := v.client.Do(req)
	if err != nil {
		return fmt.Errorf("failed to send HTTP request: %v", err)
	}
	defer resp.Body.Close()

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("token validation failed with status code: %d", resp.StatusCode)
	}

	return nil
}

// 默认HTTP超时时间
const defaultHTTPTimeout = 5 * 1000 * 1000 * 1000 // 5秒

// ErrInvalidToken 表示token无效
var ErrInvalidToken = errors.New("invalid token")

// ErrMissingToken 表示缺少token
var ErrMissingToken = errors.New("missing token")

// ErrMissingAppID 表示缺少appID
var ErrMissingAppID = errors.New("missing appID")
